package fr.univ.lille1.android.auth;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.widget.Toast;
import fr.univ.lille1.android.domain.SessionKey;
import fr.univ.lille1.android.domain.User;
import fr.univ.lille1.android.network.RequestFactory;
import fr.univ.lille1.android.network.UserMockManager;

public class TagThisClient implements AuthenticationService {
	/**
	 * Context of the application. We use it essentially for
	 * {@link SharedPreferences}.
	 */
	private final Context mContext;
	/**
	 * Callback used to notify the activity host about the connection.
	 */
	private final OnConnectionTagThis mConnection;
	/**
	 * Callback used to notify the activity host when the connection failed.
	 */
	private final OnConnectionFailedTagThis mConnectionFailed;
	/**
	 * Current user of the session.
	 */
	private User mCurrentUser;
	/**
	 * Manager to send a request on the TagThis server to sign in a user.
	 */
	private final UserMockManager mUserManager;

	public TagThisClient(Context context, OnConnectionTagThis connection,
			OnConnectionFailedTagThis connectionFailed) {
		mContext = context;
		mConnection = connection;
		mConnectionFailed = connectionFailed;
		mUserManager = new UserMockManager(RequestFactory.getInstance()
				.getRestAdapter());
	}

	@Override
	public void connection() {
		if (isConnected()) {
			// The user is already connected and his token is valid. The user
			// can open the application.
			mCurrentUser = SessionStore.restoreUser(mContext);
			mConnection.onConnected();
			return;
		} else {
			// The user isn't connected. He must login.
			mConnectionFailed.onConnectionFailed();
			return;
		}
	}

	@Override
	public void connection(String login, String password) {
		if (isConnected()) {
			// The user is already connected and the token of his connection is
			// valid.
			mCurrentUser = SessionStore.restoreUser(mContext);
			mConnection.onConnected();
			return;
		}
		if (login == null || login.equals("")) {
			Toast.makeText(mContext, "Your login isn't valid.",
					Toast.LENGTH_LONG).show();
			mConnectionFailed.onConnectionFailed();
			return;
		}
		if (password == null || password.equals("")) {
			Toast.makeText(mContext, "Your password isn't valid.",
					Toast.LENGTH_LONG).show();
			mConnectionFailed.onConnectionFailed();
			return;
		}
		// Launches online request to login.
		new SignInAsyncTask().execute(login, password);
	}

	@Override
	public void disconnection() {
		mCurrentUser = null;
		SessionStore.flush(mContext);
	}

	@Override
	public boolean isConnected() {
		return SessionStore.isLogged(mContext)
				&& SessionStore.isConnectionValid(mContext);
	}

	@Override
	public boolean isValid() {
		return SessionStore.isConnectionValid(mContext);
	}

	@Override
	public User getCurrentUser() {
		return mCurrentUser;
	}

	private final class SignInAsyncTask extends
			AsyncTask<String, Void, SessionKey> {

		@Override
		protected SessionKey doInBackground(String... params) {
			final String email = params[0];
			final String password = params[1];
			return mUserManager.signIn(email, email, password);
		}

		@Override
		protected void onPostExecute(SessionKey result) {
			super.onPostExecute(result);
			if (result == null) {
				// Authentication failed.
				mConnectionFailed.onConnectionFailed();
				return;
			}
			mCurrentUser = result.getUser();
			SessionStore.saveUser(mContext, result.getUser());
			SessionStore.saveToken(mContext, result.getSessionKey(),
					result.getGenerateTime());
			mConnection.onConnected();
		}

	}

}
